<?php
/**
 * Processes an Order using data from the Order Data Transfer Object and the Zen Cart Database.
 * @copyright Nicolas Schudel 2008
 * @copyright Portions Copyright 2003-2006 Zen Cart Development Team
 * @copyright Portions Copyright 2003 osCommerce
 * @license http://www.gnu.org/copyleft/gpl.html GNU General Public License
 */

require_once(DTO_PATH . 'OrderDTO.php');
require_once(INTERFACES_PATH . 'IOrderable.php');

class Orders implements IOrderable {
	private $db;
	private $dto;
	private $cf;

	private $coupon;
	private $currencies;
	private $customer;
	private $delivery;
	private $info;
	private $taxes;

	private $insert_id;

	function __construct() {
		$this->db = ServiceLocator::getService('ConnectionFactory');
		$this->cf = ServiceLocator::getService('Configuration');
		$this->coupon = ServiceLocator::getService('Coupon');
		$this->currencies = ServiceLocator::getService('Currencies');
		$this->customer = ServiceLocator::getService('Customer');
		
		$this->delivery = array();
		$this->info = array();
		$this->taxes = ServiceLocator::getService('Taxes');

		$this->db->connect($this->cf->get('DB_SERVER'), $this->cf->get('DB_SERVER_USERNAME'), $this->cf->get('DB_SERVER_PASSWORD'), $this->cf->get('DB_DATABASE'), $this->cf->get('DB_USE_PCONNECT'), false);
	}
	
	public function getInsertId() {
		return $this->insert_id;
	}
	
	function find($id) {
		$orderQuery =	"SELECT o.orders_id, o.date_purchased, o.order_total, o.currency, o.payment_method
							FROM ". $this->cf->get('TABLE_ORDERS') ." o
							ORDER BY o.date_purchased DESC
							LIMIT 0 , 100";
		
		$orderList = $this->db->execute($orderQuery);
		
		$listArray = array();
		
		while (!$orderList->EOF) {
			$dto = new OrderDTO();
			$dto->oid = $orderList->fields['orders_id'];
			$dto->date = $orderList->fields['date_purchased'];
			$dto->price = $orderList->fields['order_total'];
			$dto->currency = $orderList->fields['currency'];
			$dto->method = $orderList->fields['payment_method'];
			
			// get the product ids from each order;
			$orderProductsQuery = 	"SELECT op.products_id
									FROM ".$this->cf->get('TABLE_ORDERS_PRODUCTS')." op 
									WHERE op.orders_id = '" . $orderList->fields['orders_id'] . "' 
									LIMIT 0, 100";
			$pidList = $this->db->execute($orderProductsQuery);
			$pidArray = array();
			while (!$pidList->EOF) {
				$product = new ProductDTO;
				$product->pid = $pidList->fields['products_id'];
				array_push($pidArray, $product);
				$pidList->moveNext();
			}
			$dto->pids = $pidArray;
			
			array_push($listArray, $dto);
			$orderList->moveNext();
		}
		
		return $listArray;
	}
	
	public function load(OrderDTO $dto) {
		if (!isset($dto)) throw new Exception ("OrderDTO not set");
		$this->dto = $dto;
		
		$customer_address_query = "select c.customers_firstname, c.customers_lastname, c.customers_telephone,
									c.customers_email_address, ab.entry_company, ab.entry_street_address,
									ab.entry_suburb, ab.entry_postcode, ab.entry_city, ab.entry_zone_id, ab.entry_state,
									z.zone_name, co.countries_id, co.countries_name,
									co.countries_iso_code_2, co.countries_iso_code_3,
									co.address_format_id, ab.entry_state
									from (" . $this->cf->get('TABLE_CUSTOMERS') . " c, " . $this->cf->get('TABLE_ADDRESS_BOOK') . " ab )
									left join " . $this->cf->get('TABLE_ZONES') . " z on (ab.entry_zone_id = z.zone_id)
									left join " . $this->cf->get('TABLE_COUNTRIES') . " co on (ab.entry_country_id = co.countries_id)
									where c.customers_id = '" . (int)$this->cf->get('POS_DEFAULT_CUSTOMER') . "'
									and ab.customers_id = '" . (int)$this->cf->get('POS_DEFAULT_CUSTOMER') . "'
									and c.customers_default_address_id = ab.address_book_id";
		
		$customer_address = $this->db->execute($customer_address_query);
		
		$shipping_address_query = "select ab.entry_firstname, ab.entry_lastname, ab.entry_company,
									ab.entry_street_address, ab.entry_suburb, ab.entry_postcode,
									ab.entry_city, ab.entry_zone_id, z.zone_name, ab.entry_country_id,
									c.countries_id, c.countries_name, c.countries_iso_code_2,
									c.countries_iso_code_3, c.address_format_id, ab.entry_state
									from " . $this->cf->get('TABLE_ADDRESS_BOOK') . " ab
									left join " . $this->cf->get('TABLE_ZONES') . " z on (ab.entry_zone_id = z.zone_id)
									left join " . $this->cf->get('TABLE_COUNTRIES') . " c on (ab.entry_country_id = c.countries_id) 
									where ab.customers_id = '" . (int)$this->cf->get('POS_DEFAULT_CUSTOMER') . "'
									and ab.address_book_id = '" . (int)$this->cf->get('POS_DEFAULT_CUSTOMER') . "'";
		
		$shipping_address = $this->db->execute($shipping_address_query);
		
		$billing_address_query = "select ab.entry_firstname, ab.entry_lastname, ab.entry_company,
									ab.entry_street_address, ab.entry_suburb, ab.entry_postcode,
									ab.entry_city, ab.entry_zone_id, z.zone_name, ab.entry_country_id,
									c.countries_id, c.countries_name, c.countries_iso_code_2,
									c.countries_iso_code_3, c.address_format_id, ab.entry_state
									from " . $this->cf->get('TABLE_ADDRESS_BOOK') . " ab
									left join " . $this->cf->get('TABLE_ZONES') . " z on (ab.entry_zone_id = z.zone_id)
									left join " . $this->cf->get('TABLE_COUNTRIES') . " c on (ab.entry_country_id = c.countries_id) 
									where ab.customers_id = '" . (int)$this->cf->get('POS_DEFAULT_CUSTOMER') . "'
									and ab.address_book_id = '" . (int)$this->cf->get('POS_DEFAULT_CUSTOMER') . "'";
		
		$billing_address = $this->db->execute($billing_address_query);

		
		$this->info =		array('order_status' => $this->cf->get('POS_DEFAULT_ORDER_STATUS'),
								'currency' => ($this->currencies->currencyExists($this->dto->currency) ? $this->dto->currency : $this->currencies->getDefaultCurrency()),
								'currency_value' => ($this->currencies->currencyExists($this->dto->currency) ? $this->currencies->get_value($this->dto->currency) : 1),
								'payment_method' => "Cash on Delivery",
								'payment_module_code' => "cod",
								'coupon_code' => "",
								'shipping_method' => "Store Pickup (Walk In)",
								'shipping_module_code' => "storepickup",
								'shipping_cost' => 0,
								'subtotal' => $this->dto->price,
								'cc_type' => "",
								'cc_owner' => "",
								'cc_number' => "",
								'cc_expires' => "",
								'tax' => 0,
								'total' => null,
								'tax_groups' => array(),
								'comments' => (isset($this->dto->cashier->name) ? $this->cf->get('POS_DEFAULT_ORDER_COMMENTS') . $this->dto->cashier->name : null),
								'ip_address' => 0
								);
								

		if ($this->cf->get('DISPLAY_PRICE_WITH_TAX') == 'true') {
			$this->info['total'] = $this->info['subtotal'] + $this->info['shipping_cost'];
		} else {
			$this->info['total'] = $this->info['subtotal'] + $this->info['tax'] + $this->info['shipping_cost'];
		}
		
		$this->customer = array('firstname' => $customer_address->fields['customers_firstname'],
								'lastname' => $customer_address->fields['customers_lastname'],
								'company' => $customer_address->fields['entry_company'],
								'street_address' => $customer_address->fields['entry_street_address'],
								'suburb' => $customer_address->fields['entry_suburb'],
								'city' => $customer_address->fields['entry_city'],
								'state' => $customer_address->fields['entry_state'],
								'postcode' => $customer_address->fields['entry_postcode'],
								'state' => ((!empty($customer_address->fields['entry_state'])) ? $customer_address->fields['entry_state'] : $customer_address->fields['zone_name']),
								'zone_id' => $customer_address->fields['entry_zone_id'],
								'country' => array('id' => $customer_address->fields['countries_id'], 'title' => $customer_address->fields['countries_name'], 'iso_code_2' => $customer_address->fields['countries_iso_code_2'], 'iso_code_3' => $customer_address->fields['countries_iso_code_3']),
								'format_id' => $customer_address->fields['address_format_id'],
								'telephone' => $customer_address->fields['customers_telephone'],
								'email_address' => $customer_address->fields['customers_email_address']
								);
		
		$this->delivery = array('firstname' => $shipping_address->fields['entry_firstname'],
								'lastname' => $shipping_address->fields['entry_lastname'],
								'company' => $shipping_address->fields['entry_company'],
								'street_address' => $shipping_address->fields['entry_street_address'],
								'suburb' => $shipping_address->fields['entry_suburb'],
								'city' => $shipping_address->fields['entry_city'],
								'postcode' => $shipping_address->fields['entry_postcode'],
								'state' => ((!empty($shipping_address->fields['entry_state'])) ? $shipping_address->fields['entry_state'] : $shipping_address->fields['zone_name']),
								'zone_id' => $shipping_address->fields['entry_zone_id'],
								'country' => array('id' => $shipping_address->fields['countries_id'], 'title' => $shipping_address->fields['countries_name'], 'iso_code_2' => $shipping_address->fields['countries_iso_code_2'], 'iso_code_3' => $shipping_address->fields['countries_iso_code_3']),
								'country_id' => $shipping_address->fields['entry_country_id'],
								'format_id' => $shipping_address->fields['address_format_id']
								);
		
		$this->billing =	array('firstname' => $billing_address->fields['entry_firstname'],
								'lastname' => $billing_address->fields['entry_lastname'],
								'company' => $billing_address->fields['entry_company'],
								'street_address' => $billing_address->fields['entry_street_address'],
								'suburb' => $billing_address->fields['entry_suburb'],
								'city' => $billing_address->fields['entry_city'],
								'postcode' => $billing_address->fields['entry_postcode'],
								'state' => ((!empty($billing_address->fields['entry_state'])) ? $billing_address->fields['entry_state'] : $billing_address->fields['zone_name']),
								'zone_id' => $billing_address->fields['entry_zone_id'],
								'country' => array('id' => $billing_address->fields['countries_id'], 'title' => $billing_address->fields['countries_name'], 'iso_code_2' => $billing_address->fields['countries_iso_code_2'], 'iso_code_3' => $billing_address->fields['countries_iso_code_3']),
								'country_id' => $billing_address->fields['entry_country_id'],
								'format_id' => $billing_address->fields['address_format_id']
								);
	}

	public function save($insert_id) {
		
		/* Update the Orders Table */
		$sql_data_array = array('customers_id' => $this->cf->get('POS_DEFAULT_CUSTOMER'),
								'customers_name' => $this->customer['firstname'] . ' ' . $this->customer['lastname'],
								'customers_company' => $this->customer['company'],
								'customers_street_address' => $this->customer['street_address'],
								'customers_suburb' => $this->customer['suburb'],
								'customers_city' => $this->customer['city'],
								'customers_postcode' => $this->customer['postcode'],
								'customers_state' => $this->customer['state'],
								'customers_country' => $this->customer['country']['title'],
								'customers_telephone' => $this->customer['telephone'],
								'customers_email_address' => $this->customer['email_address'],
								'customers_address_format_id' => $this->customer['format_id'],
								'delivery_name' => $this->delivery['firstname'] . ' ' . $this->delivery['lastname'],
								'delivery_company' => $this->delivery['company'],
								'delivery_street_address' => $this->delivery['street_address'],
								'delivery_suburb' => $this->delivery['suburb'],
								'delivery_city' => $this->delivery['city'],
								'delivery_postcode' => $this->delivery['postcode'],
								'delivery_state' => $this->delivery['state'],
								'delivery_country' => $this->delivery['country']['title'],
								'delivery_address_format_id' => $this->delivery['format_id'],
								'billing_name' => $this->billing['firstname'] . ' ' . $this->billing['lastname'],
								'billing_company' => $this->billing['company'],
								'billing_street_address' => $this->billing['street_address'],
								'billing_suburb' => $this->billing['suburb'],
								'billing_city' => $this->billing['city'],
								'billing_postcode' => $this->billing['postcode'],
								'billing_state' => $this->billing['state'],
								'billing_country' => $this->billing['country']['title'],
								'billing_address_format_id' => $this->billing['format_id'],
								'payment_method' => (($this->info['payment_module_code'] == '' and $this->info['payment_method'] == '') ? 'Gift Certificate/Coupon' : $this->info['payment_method']),
								'payment_module_code' => (($this->info['payment_module_code'] == '' and $this->info['payment_method'] == '') ? 'GV/DC' : $this->info['payment_module_code']),
								'shipping_method' => $this->info['shipping_method'],
								'shipping_module_code' => (strpos($this->info['shipping_module_code'], '_') > 0 ? substr($this->info['shipping_module_code'], 0, strpos($this->info['shipping_module_code'], '_')) : $this->info['shipping_module_code']),
								'coupon_code' => $this->info['coupon_code'],
								'cc_type' => $this->info['cc_type'],
								'cc_owner' => $this->info['cc_owner'],
								'cc_number' => $this->info['cc_number'],
								'cc_expires' => $this->info['cc_expires'],
								'date_purchased' => 'now()',
								'orders_status' => $this->info['order_status'],
								'order_total' => $this->info['total'],
								'order_tax' => $this->info['tax'],
								'currency' => $this->info['currency'],
								'currency_value' => $this->info['currency_value'],
								'ip_address' => $_SERVER['REMOTE_ADDR']
								);
		$this->db->perform($this->cf->get('TABLE_ORDERS'), $sql_data_array);
		
		$this->insert_id = $this->db->Insert_ID();
		
		/* Update the Orders Total Table */
		$sql_data_array = array('orders_id' => $this->insert_id,
								'title' => "Total:",
								'text' => $this->currencies->format($this->info['total'], false, $this->info['currency']),
								'value' => $this->info['total'],
								'class' => "ot_total",
								'sort_order' => 999);
		
		$this->db->perform($this->cf->get('TABLE_ORDERS_TOTAL'), $sql_data_array);
		
		/* Update the Orders Status History Table */
		$sql_data_array = array('orders_id' => $this->insert_id,
								'orders_status_id' => $this->info['order_status'],
								'date_added' => 'now()',
								'customer_notified' => 1,
								'comments' => $this->info['comments']);
		
		$this->db->perform($this->cf->get('TABLE_ORDERS_STATUS_HISTORY'), $sql_data_array);
		
		
		return($this->insert_id);
	}
}
?>